package com.box.app.arithmetic

import platform.posix.*
import kotlin.math.*
import kotlin.math.acos
import kotlin.math.asin
import kotlin.math.atan
import kotlin.math.atan2
import kotlin.math.cbrt
import kotlin.math.ceil
import kotlin.math.cos
import kotlin.math.cosh
import kotlin.math.exp
import kotlin.math.expm1
import kotlin.math.floor
import kotlin.math.hypot
import kotlin.math.log10
import kotlin.math.sin
import kotlin.math.sinh
import kotlin.math.sqrt
import kotlin.math.tan
import kotlin.math.tanh

@Suppress("EnumEntryName")
enum class BuiltInMath : Callable {
    // region ================ Math ========================================
    abs,
    sin,
    cos,
    tan,
    atan2,
    sqrt,
    log,
    log10,
    pow,
    exp,
    min,
    max,
    floor,
    ceil,
    rint,
    fma,
    scalb,
    asin,
    acos,
    atan,
    cbrt,
    sinh,
    cosh,
    tanh,
    hypot,
    expm1,
    log1p,
    // endregion
    ;

    override fun call(vararg values: Number): Number = when (this) {
        abs -> abs(values.single().toDouble())
        sin -> sin(values.single().toDouble())
        cos -> cos(values.single().toDouble())
        tan -> tan(values.single().toDouble())
        atan2 -> atan2(values[0].toDouble(), values[1].toDouble())
        sqrt -> sqrt(values.single().toDouble())
        log -> log(values[0].toDouble(), values[1].toDouble())
        log10 -> log10(values.single().toDouble())
        pow -> pow(values[0].toDouble(), values[1].toDouble())
        exp -> exp(values.single().toDouble())
        min -> min(values[0].toDouble(), values[1].toDouble())
        max -> max(values[0].toDouble(), values[1].toDouble())
        floor -> floor(values.single().toDouble())
        ceil -> ceil(values.single().toDouble())
        rint -> rint(values.single().toDouble())
        fma -> fma(values[0].toDouble(), values[1].toDouble(), values[2].toDouble())
        scalb -> scalb(values[0].toDouble(), values[1].toDouble())
        asin -> asin(values.single().toDouble())
        acos -> acos(values.single().toDouble())
        atan -> atan(values.single().toDouble())
        cbrt -> cbrt(values.single().toDouble())
        sinh -> sinh(values.single().toDouble())
        cosh -> cosh(values.single().toDouble())
        tanh -> tanh(values.single().toDouble())
        hypot -> hypot(values[0].toDouble(), values[1].toDouble())
        expm1 -> expm1(values.single().toDouble())
        log1p -> log1p(values.single().toDouble())
    }
}
